#include "StdAfx.h"
#include "SystemClass.h"


CSystemClass::CSystemClass(void) : m_ApplicationName(nullptr), m_hInstance(nullptr), m_hWnd(nullptr), m_pInput(nullptr), m_pGraphics(nullptr), m_pSound(nullptr),
	m_pFPS(nullptr), m_pCPU(nullptr), m_pTimer(nullptr), m_pPosition(nullptr)
{

}


CSystemClass::~CSystemClass(void)
{
}

bool CSystemClass::Initialize()
{
	int nScreenWidth = 0;
	int nScreenHeight = 0;
	bool bResult = false;

	InitWindows(nScreenWidth, nScreenHeight);

	m_pInput = new CInputClass();
	m_pGraphics = new CGraphicsClass();

	if(m_pInput == nullptr)
	{
		DEBUG_OUTPUT("Failed to create the Input pointer");
		return false;
	}

	if(m_pGraphics == nullptr)
	{
		DEBUG_OUTPUT("Failed to create the Graphics pointer");
		return false;
	}

	bResult = m_pInput->Initialize(m_hInstance, m_hWnd, nScreenWidth, nScreenHeight);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize the input pointer");
		return false;
	}

	bResult = m_pGraphics->Initialize(nScreenWidth, nScreenHeight, m_hWnd);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize the graphics pointer");
		return false;
	}

	m_pSound = new CSoundClass();
	if(m_pSound == nullptr)
	{
		DEBUG_OUTPUT("Failed to create new sound pointer");
		return false;
	}

	bResult = m_pSound->Initialize(m_hWnd);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize sound pointer");
		return false;
	}

	m_pFPS = new CFPSClass();
	if(m_pFPS == nullptr)
	{
		DEBUG_OUTPUT("Failed to create fps pointer");
		return false;
	}

	m_pFPS->Initialize();

	m_pCPU = new CCPUClass();
	if(m_pCPU == nullptr)
	{
		DEBUG_OUTPUT("Failed to create cpu pointer");
		return false;
	}

	m_pCPU->Initialize();

	m_pTimer = new CTimerClass();
	if(m_pTimer == nullptr)
	{
		DEBUG_OUTPUT("Failed to create timer pointer");
		return false;
	}

	bResult = m_pTimer->Initialize();
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to initialize timer pointer");
		return false;
	}

	m_pPosition = new CPositionClass();
	if(m_pPosition == nullptr)
	{
		DEBUG_OUTPUT("Failed to create new position pointer");
		return false;
	}

	return true;
}

void CSystemClass::Run()
{
	MSG msg;
	bool bDone = false;
	bool bResult = false;

	ZeroMemory(&msg, sizeof(msg));

	while(bDone == false)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		if(msg.message == WM_QUIT)
		{
			bDone = true;
		}
		else
		{
			bResult = Frame();

			if(bResult == false)
			{
				bDone = true;
			}
		}

		if(m_pInput->IsEscapePressed() == true)
		{
			bDone = true;
		}
	}
}

void CSystemClass::ShutDown()
{
	if(m_pPosition != nullptr)
	{
		delete m_pPosition;
		m_pPosition = nullptr;
	}
	
	if(m_pTimer != nullptr)
	{
		delete m_pTimer;
		m_pTimer = nullptr;
	}

	if(m_pCPU != nullptr)
	{
		m_pCPU->ShutDown();
		delete m_pCPU;
		m_pCPU = nullptr;
	}

	if(m_pFPS != nullptr)
	{
		delete m_pFPS;
		m_pFPS = nullptr;
	}

	if(m_pSound != nullptr)
	{
		m_pSound->ShutDown();
		delete m_pSound;
		m_pSound = nullptr;
	}

	if(m_pGraphics != nullptr)
	{
		m_pGraphics->ShutDown();
		delete m_pGraphics;
		m_pGraphics = nullptr;
	}

	if(m_pInput != nullptr)
	{
		m_pInput->ShutDown();
		delete m_pInput;
		m_pInput = nullptr;
	}

	ShutDownWindows();
}

bool CSystemClass::Frame()
{
	bool bResult = false;
	bool bKeyDown = false;
	float fYRot;
	//int nMouseXPos = 0;
	//int nMouseYPos = 0;

	m_pTimer->Frame();
	//m_pFPS->Frame();
	//m_pCPU->Frame();

	bResult = m_pInput->Frame();
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to get the input frame");
		return false;
	}

	//m_pInput->GetMouseLocation(nMouseXPos, nMouseYPos);
	m_pPosition->SetFrameTime(m_pTimer->GetTime());

	bKeyDown = m_pInput->IsLeftArrowPressed();
	m_pPosition->TurnLeft(bKeyDown);

	bKeyDown = m_pInput->IsRightArrowPressed();
	m_pPosition->TurnRight(bKeyDown);

	m_pPosition->GetRotation(fYRot);
	
	bResult = m_pGraphics->Frame(fYRot);
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to get the graphics frame");
		return false;
	}

	//static float fRotation = 0.0f;

	//fRotation += (float)D3DX_PI * 0.005f;
	//if(fRotation > 360)
	//{
	//	fRotation = 0.0f;
	//}

	bResult = m_pGraphics->Render();
	if(bResult == false)
	{
		DEBUG_OUTPUT("Failed to render the graphics pointer");
		return false;
	}

	return true;
}

void CSystemClass::InitWindows(int& nScreenWidth, int& nScreenHeight)
{
	WNDCLASSEX wc;
	DEVMODE dmScreenSettings;
	int nPosX = 0;
	int nPosY = 0;

	pAppHandle = this;

	m_hInstance = GetModuleHandle(NULL);

	m_ApplicationName = L"Engine";

	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = m_hInstance;
	wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
	wc.hIconSm = wc.hIcon;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = m_ApplicationName;
	wc.cbSize = sizeof(WNDCLASSEX);

	RegisterClassEx(&wc);

	nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
	nScreenHeight = GetSystemMetrics(SM_CYSCREEN);

	if(FULL_SCREEN)
	{
		memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
		dmScreenSettings.dmSize = sizeof(dmScreenSettings);
		dmScreenSettings.dmPelsWidth = (unsigned int)nScreenWidth;
		dmScreenSettings.dmPelsHeight = (unsigned int)nScreenHeight;
		dmScreenSettings.dmBitsPerPel = 32;
		dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);

		nPosX = 0;
		nPosY =	0;
	}
	else
	{
		nScreenWidth = 800;
		nScreenHeight = 600;

		nPosX = (GetSystemMetrics(SM_CXSCREEN) - nScreenWidth) / 2;
		nPosY = (GetSystemMetrics(SM_CYSCREEN) - nScreenHeight) / 2;
	}

	m_hWnd = CreateWindowEx(WS_EX_APPWINDOW, m_ApplicationName, m_ApplicationName, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP, nPosX, nPosY, nScreenWidth, nScreenHeight, NULL, NULL, m_hInstance, NULL);

	ShowWindow(m_hWnd, SW_SHOW);
	SetForegroundWindow(m_hWnd);
	SetFocus(m_hWnd);

	ShowCursor(false);
}

void CSystemClass::ShutDownWindows()
{
	ShowCursor(true);

	if(FULL_SCREEN)
	{
		ChangeDisplaySettings(NULL, 0);
	}

	DestroyWindow(m_hWnd);
	m_hWnd = NULL;

	UnregisterClass(m_ApplicationName, m_hInstance);
	m_hInstance = NULL;

	pAppHandle = NULL;
}

LRESULT CALLBACK CSystemClass::MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{	
	return DefWindowProc(hWnd, uMsg, wParam, lParam);	
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		}

	case WM_CLOSE:
		{
			PostQuitMessage(0);
			return 0;
		}

	default:
		{
			return pAppHandle->MessageHandler(hWnd, uMsg, wParam, lParam);
		}
	}
}